// 1：创建myPromiser类
// 2：加 入constructor执行器 会立即执行
// 3：会传入两个默认方法 resolve,reject
// 4: 定义三个状态 等待 成功 失败
// 5：定义一个状态status 等于pending
// 6: 定义两个方法 resolve 成功 reject 失败方法
// 7：promise 只能从等待进入成功 或者等待进入失败 //确定就不可更改
// 8：只能成功或者失败 所以 必须从等待进入 so 判断等待状态
// 9:定义then 方法 会传入两个回调函数 successCallback 成功回调 errorCallback 失败回调
// 10:then 根据状态来判断 回调什么参数
// 11: resolve，reject 都会携带一个值 这个值得保存到对象里 初始化成功回调值 与失败回调值
// -------------------
// 异步
// 1.将成功回调与异步回调存储起来
// 2.定义成功回调 和 失败回调
// 3.在then中把接收到的成功回调与失败回调 存储到定义的成功回调与失败回调
// 4.在成功方法与失败方法判断是否有对应的回调 resolve reject
// ---------------
// then方法多次调用
// 1.如果是异步的话多次调用
// 2：修改定义成功回调与失败回调为数组
// 3:then 运行 等待时候把 对应的成功回调与失败回调push相应的 定义回调中
// 4：分别执行成功和失败函数中 循环 删除第一个 while 并且赋值

// 链式调用 后一个回调函数的值是上一个回调函数的返回值（每一个方法都是promise对象）
// 1：在then中创建一个promise对象
// 2 把之前then里的方法放入new mypromise中 并且return promise
// 3 把之前的successCallback 声明一个变量
// 4 新建的new MYpromise 添加两个参数 resolve，reject;
// 5 执行成功回调resolve（）传入声明的变量
// 6 判断声明的变量是普通值还是promise对象 如果是promise对象 查看promise返回结果
// 7 再根据结果决定调用resolve，reject
// 8 定义一个公告方法resolvePromise方法 //传入3个值 定义的x变量 resolve，reject
// 9 如果返回是本身的promise对象 执行reject方法 防止自己返回自己
// 10 为了获取promise2 把代码变成异步代码 settimeout 方法
// ------
// 错误处理
// 再执行器中用 try catch 捕获错误
// then 方法中捕获错误

// ---
// then方法中不传递参数 promise一次传递直到有回调函数的参数

// ---
// all //解决异步并发问题
// 输入[a,b,c,d] 输出结果[a,b,c,d];
// promise.all([a,b,c,d]).then((res)=>{
// res->[a,b,c,d]
// })
// 异步代码调用顺序 得到异步代码调用结果
// 全部执行成功才成功，只要有一个结果失败，返回失败。
// 1:声明一个静态方法 static all (array) 接收一个array 参数
// 2:返回值 一个promise对象
// 3：循环这个数组
// 4：声明一个result数组 存储array参数
// 5 判断每一个参数类型 是promise对象的话 直接运行then方法，如果普通值运行addData方法
// -----------
// resolve
// 返回一个promise 对象
// 判断是否promise、对象 是->直接返回 否->创建promise对象返回

// -----
// finally
// 无论成功还是失败 finally都会执行一次
// then 拿到当前promise 最终结果
// ------------
// catch
// 错误回调

const PENDINGG = "pending"; //等待
const FUIFLLED = "fuiflled"; //成功
const REJECTED = "rejected"; //失败
class myPromise {
  constructor(executor) {
    try {
      executor(this.resolve, this.reject);
    } catch (e) {
      //捕获错误
      this.reject(e);
    }
  }
  //状态
  status = PENDINGG;
  //成功值
  value = undefined;
  //失败值
  error = undefined;
  //成功回调
  successCallback = [];
  //失败回调
  errorCallback = [];
  //成功方法
  resolve = (value) => {
    //判断等待状态
    if (this.status !== PENDINGG) return;
    //修改状态 失败
    this.status = FUIFLLED; //成功！
    //把当前接收到的值 赋值给成功回调值
    this.value = value;
    //判断是否有成功回调 存在就调用
    //this.successCallback && this.successCallback(this.value)
    while (this.successCallback.length) {
      this.successCallback.shift()();
    }
  };
  //失败方法
  reject = (error) => {
    //判断等待状态
    if (this.status !== PENDINGG) return;
    //修改状态 失败
    this.status = REJECTED;
    //把当前接收到的值 赋值给失败回调值
    this.error = error;
    //判断是否有成功回调 存在就调用
    this.errorCallback && this.errorCallback(this.error);
    //失败之后删除 errorCallback
    //this.errorCallback.shift()
    while (this.errorCallback.length) {
      this.errorCallback.shift()();
    }
  };
  then(successCallback, errorCallback) {
    successCallback = successCallback ? successCallback : (value) => value; //传递正确回调信息
    errorCallback = errorCallback
      ? errorCallback
      : (reson) => {
          throw reson;
        }; //传递错误信息
    let promise2 = new myPromise((resolve, reject) => {
      //判断状态、
      if (this.status === FUIFLLED) {
        //捕获错误
        try {
          setTimeout(() => {
            //变为异步代码
            //成功回调
            let x = successCallback(this.value);
            // resolve(x);
            resolvePromise(promise2, x, resolve, reject);
          }, 0);
        } catch (e) {
          reject(e);
        }
      } else if (this.successCallback === REJECTED) {
        //失败回调
        //捕获错误
        try {
          setTimeout(() => {
            //变为异步代码
            //成功回调
            let x = errorCallback(this.error);
            // resolve(x);
            resolvePromise(promise2, x, resolve, reject);
          }, 0);
        } catch (e) {
          reject(e);
        }
      } else {
        // 将成功回调与异步回调存储起来
        this.successCallback.push(() => {
          try {
            setTimeout(() => {
              //变为异步代码
              //成功回调
              let x = successCallback(this.value);
              // resolve(x);
              resolvePromise(promise2, x, resolve, reject);
            }, 0);
          } catch (e) {
            reject(e);
          }
        });
        this.errorCallback.push(() => {
          try {
            setTimeout(() => {
              //变为异步代码
              //成功回调
              let x = errorCallback(this.error);
              // resolve(x);
              resolvePromise(promise2, x, resolve, reject);
            }, 0);
          } catch (e) {
            reject(e);
          }
        });
        //    this.successCallback=successCallback;
        //    this.errorCallback=errorCallback;
      }
    });
    return promise2;
  }
  static all(array) {
    let result = [];
    let index = 0; //与index相关 等待异步操作结果
    return new myPromise((resolve, reject) => {
      function addData(key, value) {
        result[key] = value;
        index++;
        if (index === array.length) {
          resolve(result);
        }
      }
      for (let i = 0; i < array.length; i++) {
        //
        let current = array[i];
        //判断current类型
        if (current instanceof myPromise) {
          //promise对象
          current.then(
            (value) => addData(value),
            (reason) => reject(reason)
          ); //当前为异步操作  循环未等待
        } else {
          //普通值
          addData(i, array[i]);
        }
      }
    });
  }
  static resolve(value) {
    if (value instanceof myPromise) return value; //是 直接返回值
    return new myPromise((resolve) => resolve(value)); //否 直接返回promise对象
  }
  finally(callBack) {
    return this.then(
      (value) => {
        return myPromise.resolve(callBack()).then(() => value);
      },
      () => {
        return myPromise.resolve(callBack()).then(() => {
          throw reason;
        });
      }
    );
  }
  catch(failCallback) {
    return this.then(undefined, failCallback);
  }
}
//公共方法
function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === resolve) {
    return reject(new Error("类型错误"));
  }
  if (x instanceof myPromise) {
    //promise 对象
    x.then(resolve, reject);
  } else {
    //普通值
    resolve(x);
  }
}